#light

/// File: VSLabShellPackage\VSLabPerfMon.fs
/// 
/// Author: Antonio Cisternino (cisterni@di.unipi.it)
///   
/// ------------------------------------------------------------
/// Copyright (c) Microsoft Corporation.  All rights reserved.
/// 
/// The use and distribution terms for this software are 
/// contained in the file named license.txt, which can be found 
/// in the root of this distribution.
/// By using this software in any fashion, you are agreeing to 
/// be bound by the terms of this license.
///
/// You must not remove this notice, or any other, from this
/// software.
/// ------------------------------------------------------------

namespace VSLabPerfMonViewlet

open System
open System.ComponentModel
open System.Drawing
open System.Drawing.Drawing2D
open System.Windows.Forms
open System.Diagnostics

open VSLab

type VSMon() as x = 
  inherit Viewlet() as base
  let mutable lastRead = DateTime.Now
  let mutable vscput = new TimeSpan()
  let mutable fsicput = new TimeSpan()
  let mutable vsCPU = 0
  let mutable fsCPU = 0
  let mutable wsSz = 0f
  let mutable msSz = 0f
  let mutable showMemory = true
  
  let Title = "VSLab Performance Monitor"

  let t = new Timer()
  
  let CPUTime () =
    let vp = Process.GetProcessById(VSLab.Environment.VSPID())
    let fp = Process.GetCurrentProcess()
    let now = DateTime.Now
    vsCPU <- Math.Min(int (100.0 * (vp.TotalProcessorTime - vscput).TotalMilliseconds / (now - lastRead).TotalMilliseconds), 100)
    fsCPU <- Math.Min(int (100.0 * (fp.TotalProcessorTime - fsicput).TotalMilliseconds / (now - lastRead).TotalMilliseconds), 100)
    lastRead <- now
    vscput <- vp.TotalProcessorTime
    fsicput <- fp.TotalProcessorTime
    msSz <- float32(fp.PrivateMemorySize64) / (1024f*1024f)
    wsSz <- float32(fp.WorkingSet64)  / (1024f*1024f)
      
  do
    x.BackColor <- Color.Navy
    x.Font <- new Font("Verdana", 6f)
    x.Name <- Title
    
    for v in VSLab.Viewlets.Items() do
      if v.Name = Title then failwith "Only one instance of Perf mon is allowed!"
    
    t.Interval <- 500
    t.Tick.Add(fun _ -> CPUTime(); x.Invalidate())

  [<Category("Perfmon Style")>]    
  member x.Background 
    with get() = x.BackColor
    and set c = x.BackColor <- c

  [<Category("Perfmon Style")>]    
  member x.ShowMemory 
    with get() = showMemory
    and set m = showMemory <- m; x.Invalidate()
  
  override x.OnPaint(e) =
    let g = e.Graphics
    let drawBar title v (p:PointF) =
      let r = new RectangleF(float32 p.X, float32 p.Y, 100.0f, 10.0f)
      use b = new LinearGradientBrush(new Point(int p.X, int (p.Y + (r.Height / 2.0f))), new Point(int (p.X + r.Width), int (p.Y + (r.Height / 2.0f))), Color.Green, Color.Red )
      g.FillRectangle(Brushes.LightBlue, r)
      g.FillRectangle(b, r.Left, r.Top, ((float32 v)/100f) * r.Width, r.Height)
      g.DrawRectangle(Pens.Blue, r.Left, r.Top, r.Width, r.Height)
      g.DrawString(title, x.Font, Brushes.White, r)
    
    drawBar ("VS: "+vsCPU.ToString()+"%") vsCPU (new PointF(10.0f, 5.0f))
    drawBar ("FS: "+fsCPU.ToString()+"%") fsCPU (new PointF(10.0f, 17.0f))
    
    if showMemory then
      g.DrawString(string.Format("F# ws: {0:f3}Mb", wsSz), x.Font, Brushes.White, new RectangleF(115f, 5f, 100f, 10f))
      g.DrawString(string.Format("F# mem: {0:f3}Mb", msSz), x.Font, Brushes.White, new RectangleF(115f, 17f, 100f, 10f))
    
    
  override x.OnViewletVisibilityChange v =
    if v then t.Start()
    else t.Stop()
  
  override x.BrowsableCategories () = [| "Perfmon Style" |]
  
  interface IDisposable with
    member x.Dispose () = t.Stop()